package com.boby.homecamera.helper

import android.media.MediaCodec
import android.media.MediaFormat
import android.media.MediaMuxer
import android.util.Log
import com.pedro.common.isKeyframe
import com.boby.homecamera.App
import com.boby.homecamera.config.AppConfig
import com.boby.homecamera.copy
import com.boby.homecamera.data.RecordMediaFrame
import com.boby.homecamera.db.DBManager
import com.boby.homecamera.db.VideoTable
import com.boby.homecamera.service.MainService
import com.boby.homecamera.util.FileUtil
import com.boby.lib_common.BaseApplication
import java.io.File
import java.nio.ByteBuffer
import java.util.concurrent.BlockingQueue
import java.util.concurrent.LinkedBlockingQueue

class WriteRecordFileHelper (var audioFormat: MediaFormat,var videoFormat: MediaFormat) {
    private val TAG = "WriteRecordFileHelper"
    private var isStart = false
    private var workThread:Thread? = null
    private var lastWriteTime = 0L
    private var createVideoFileTime = 0L//创建新的mp4时间
    private var queue: BlockingQueue<RecordMediaFrame> = LinkedBlockingQueue()

    private var mediaMuxer: MediaMuxer? = null
    private var videoTrack: Int = -1
    private var audioTrack: Int = -1
    private var lastVideo :VideoTable.Video? = null
    private var lastVideoPath:String? = null

    var videoWidth:Int = 0
    var videoHeight:Int = 0

    fun writeVideo(videoBuffer: ByteBuffer, info: MediaCodec.BufferInfo){
        if(!isStart){
            return
        }
        try {
//            Log.d(TAG,"writeVideo:${info.presentationTimeUs} -> ${System.currentTimeMillis()}")
            queue.put(RecordMediaFrame(videoBuffer.copy(), info.copy(), RecordMediaFrame.Type.VIDEO, System.currentTimeMillis()))
        }catch (e:Exception){
            e.printStackTrace()
        }
    }

    fun writeAudio(audioBuffer: ByteBuffer, info: MediaCodec.BufferInfo){
        if(!isStart){
            return
        }
        try {
            queue.put(RecordMediaFrame(audioBuffer.copy(), info.copy(), RecordMediaFrame.Type.AUDIO, System.currentTimeMillis()))
        }catch (e:Exception){
            e.printStackTrace()
        }
    }

    @Synchronized
    fun start(){
        if(isStart){
            return
        }
        isStart = true
        workThread = Thread {

            while (isStart){
                try {
                    val frame = queue.take()
                    if(System.currentTimeMillis() - lastWriteTime > 60000 * 1){ //300000
                        // 每隔5分钟写一个新文件
                        //视频首帧必须是关键帧
                        if(frame.type == RecordMediaFrame.Type.VIDEO && frame.info.isKeyframe()){
                            lastWriteTime = System.currentTimeMillis()
                            createVideoFileTime = frame.time!!
                            stopRecord(createVideoFileTime)
                            startNewRecord(createVideoFileTime)
                        }
                    }
                    if(frame.type == RecordMediaFrame.Type.VIDEO){
                        write(videoTrack, frame.data, frame.info)
                    }else{
                        write(audioTrack, frame.data, frame.info)
                    }



                }catch (e:Exception){
                    e.printStackTrace()
                }

            }
            stopRecord(System.currentTimeMillis())
        }
        workThread?.start()
    }

    private fun stopRecord( stopTime:Long){
        if(mediaMuxer!=null){
            mediaMuxer?.stop()
            mediaMuxer?.release()
            mediaMuxer = null
            videoTrack = -1
            audioTrack = -1
            mediaMuxer  = null

            if(lastVideo?.id != null && lastVideo?.id != -1L){
                lastVideoPath?.let {
                    val lastFile = File(it)
                    if(lastFile.exists()){
                        lastVideo!!.length = lastFile.length()
                    }
                }
                lastVideo!!.endTime = stopTime

                DBManager.instance.tb_video.updateVideo(lastVideo!!)
                lastVideo = null
            }

        }

    }
    private fun startNewRecord(createTime:Long){
//        Log.d(TAG,"startNewRecord")
        try {
            //时间戳转格式化 时间戳转日期格式
//            val time = System.currentTimeMillis()
//            val date = java.util.Date(time)
//            val format = SimpleDateFormat("yyyy_MM_dd HH:mm:sss", Locale.getDefault())
//            val fileName = format.format(date)
            val dir = File(com.boby.homecamera.constant.Constant.RECORD_FILE_DIR)
            if(!dir.exists()){
                dir.mkdirs()
            }
            checkMaxSize(dir)
            val path = "${com.boby.homecamera.constant.Constant.RECORD_FILE_DIR}${System.currentTimeMillis()}"
            lastVideoPath = "${path}.mp4"
            mediaMuxer = MediaMuxer(lastVideoPath!!, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
            audioTrack = mediaMuxer!!.addTrack(audioFormat)
            videoTrack = mediaMuxer!!.addTrack(videoFormat)
            mediaMuxer?.start()
            lastVideo = VideoTable.Video(width = videoWidth,height = videoHeight,path = lastVideoPath!!, startTime = createTime)
            val id = DBManager.instance.tb_video.insertVideo(lastVideo!!)
            lastVideo?.id = id
            takePhoto("${path}.jpeg")
        }catch (e:Exception){
            e.printStackTrace()
        }
    }
    private fun takePhoto(path:String){
        MainService.recordServer?.glInterface?.takePhoto(videoWidth/2,videoHeight/2){
            try {
                BaseApplication.getWorkHandler()?.post {
                    FileUtil.saveBitmapToDir(it,null,path)
                }
            }catch (e:Exception){
                e.printStackTrace()
            }

        }
    }


    private fun write(track: Int, byteBuffer: ByteBuffer, info: MediaCodec.BufferInfo) {
        try {
            mediaMuxer?.writeSampleData(track, byteBuffer, info)

        } catch (e:Exception) {
//            e.printStackTrace()
        }
    }

    @Synchronized
    fun stop(){
        workThread?.interrupt()
        workThread = null
        isStart = false
        lastWriteTime = 0L

    }

    private fun checkMaxSize(dir:File){
        val listFile = dir.listFiles()
        var allSize = 0L
        if(listFile == null){
            return
        }
        val maxSaveSize = com.boby.homecamera.util.StorageUtil.getAvailableExternalStorage(
            BaseApplication.instance()) - 1024*1024*1024*5 //24353001472
//        Log.d(TAG,"checkMaxSize: $maxSaveSize")
        listFile.sortDescending()

        listFile.forEach {
            if(it.isFile){
                if(allSize >= AppConfig.Record.RECORD_FILE_MAX_SIZE || allSize >= maxSaveSize){
                    it.delete()
//                Log.d(TAG,"delete file1 $allSize ${Constant.RECORD_FILE_MAX_SIZE} -> ${it.path}")
                }else{
                    allSize += it.length()

                    if(allSize >= AppConfig.Record.RECORD_FILE_MAX_SIZE || allSize >= maxSaveSize){
                        it.delete()
//                    Log.d(TAG,"delete file2 $allSize ${Constant.RECORD_FILE_MAX_SIZE} ->  ${it.path}")
                    }

                }
            }


        }

    }

}

